package com.fengchao.util.common;

import jodd.datetime.JDateTime;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class DateUtil {

    /**
     * 格式 2015-08-07
     */
    public static final String DateFormat_yyyyMMdd = "yyyy-MM-dd";
    /**
     * 15:25:30
     */
    public static final String DateFormat_HHmmss = "HH:mm:ss";

    public static final String DateFormat_yyyyMM = "yyyy-MM";
    /**
     * 格式 2015-08-07 11:44:18
     */
    public static final String DateFormat_yyyyMMddHHmmss = "yyyy-MM-dd HH:mm:ss";

    /**
     * 格式 150807114418
     */
    public static final String DateFormat_yyMMddHHmmss = "yyMMddHHmmss";
    /**
     * 格式 2015-08-07 11:44:18:591
     */
    public static final String DateFormat_yyyyMMddHHmmssSSS = "yyyy-MM-dd HH:mm:ss.SSS";
    /**
     * 时间戳格式
     * 格式 20150807114418591
     */
    public static final String DateFormat_TimeStemp = "yyyyMMddHHmmssSSS";
    /**
     * 时间戳格式
     * 格式 20140416142030
     */
    public static final String DateFormat_TimeStemp_yyyyMMddHHmmss = "yyyyMMddHHmmss";

    /**
     * 时间戳格式
     * 格式 2015-08-13T16:49:02.039+0800
     */
    public static final String DateFormat_yyyyMMddTHHmmssSSSZ = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";

    /**
     * 时间戳格式
     * 格式 2015-11-09T00:00:08.000+08:00
     */
    public static final String DateFormat_yyyyMMddTHHmmssSSSXXX = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";


    /**
     * 日期加年
     *
     * @param date
     * @param years
     * @return
     */
    public static Date addYear(Date date, int years) {
        JDateTime JDateTime = new JDateTime(date);
        JDateTime.addYear(years);
        return JDateTime.convertToDate();
    }


    /**
     * 日期加月数
     *
     * @param date
     * @return
     */
    public static Date addMonth(Date date, int months) {
        JDateTime JDateTime = new JDateTime(date);
        JDateTime.addMonth(months);
        return JDateTime.convertToDate();
    }

    /**
     * 日期减天数
     *
     * @param date
     * @param months
     * @return
     */
    public static Date minusMonth(Date date, int months) {
        JDateTime JDateTime = new JDateTime(date);
        JDateTime.subMonth(months);
        return JDateTime.convertToDate();
    }

    /**
     * 日期加天数
     *
     * @param date
     * @param days
     * @return
     */
    public static Date addDay(Date date, int days) {
        JDateTime JDateTime = new JDateTime(date);
        JDateTime.addDay(days);
        return JDateTime.convertToDate();
    }


    /**
     * 日期减月份
     *
     * @param date
     * @param days
     * @return
     */
    public static Date minusDay(Date date, int days) {
        JDateTime JDateTime = new JDateTime(date);
        JDateTime.subDay(days);
        return JDateTime.convertToDate();
    }

    /**
     * 日期加小时数
     *
     * @param date
     * @return
     */
    public static Date addHour(Date date, int hours) {
        JDateTime JDateTime = new JDateTime(date);
        JDateTime.addHour(hours);
        return JDateTime.convertToDate();
    }

    /**
     * 日期加分钟数
     *
     * @param date
     * @return
     */
    public static Date addMinutes(Date date, Integer minutes) {
        JDateTime JDateTime = new JDateTime(date);
        JDateTime.addMinute(minutes);
        return JDateTime.convertToDate();
    }

    /**
     * 日期加秒
     *
     * @param date
     * @return
     */
    public static Date addSecond(Date date, int second) {
        JDateTime JDateTime = new JDateTime(date);
        JDateTime.addSecond(second);
        return JDateTime.convertToDate();
    }

    /**
     * 获取指定时间的第二天
     *
     * @param date
     * @return
     */
    public static Date getTomorrowOfDate(Date date) {
        return addDay(date, 1);
    }

    /**
     * 获取date2-date1的月份差(只考虑月份)
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int getDateBetweenMonth(Date date1, Date date2) {
        Calendar c1 = Calendar.getInstance();
        c1.setTime(date1);
        Calendar c2 = Calendar.getInstance();
        c2.setTime(date2);
        int yearSub = c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR);
        int month1 = c1.get(Calendar.MONTH);
        int month2 = c2.get(Calendar.MONTH);
        return yearSub * 12 - (month1 - month2);
    }

    /**
     * 计算两个时间的月数之差(不存在负数)只考虑月份
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int monthsBetweenTwoDate(Date date1, Date date2) {
        return Math.abs(getDateBetweenMonth(date1, date2));
    }

    /**
     * 计算两个时间的天数之差(不存在负数)
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int daysBetweenTwoDate(Date date1, Date date2) {
        JDateTime JDateTime1 = new JDateTime(date1);
        JDateTime JDateTime2 = new JDateTime(date2);
        int days = JDateTime1.daysBetween(JDateTime2);
        return days;
    }

    /**
     * 计算两个时间的分钟之差(不存在负数)考虑秒数
     *
     * @param date1
     * @param date2
     * @return
     */
    public static long minutesBetweenTwoDate(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            throw new RuntimeException("求日期分钟差时日期不能为空");
        } else {
            long longValue1 = date1.getTime();
            long longValue2 = date2.getTime();
            long difference = longValue1 - longValue2;
            long differenceMin = Math.abs(difference) / (60 * 1000);
            if (Math.abs(difference) % 60 != 0) {
                differenceMin++;
            }
            return differenceMin;
        }
    }

    /**
     * 计算两个时间的秒之差(不存在负数)考虑秒数
     *
     * @param date1
     * @param date2
     * @return
     */
    public static long secondBetweenTwoDate(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            throw new RuntimeException("求日期分钟差时日期不能为空");
        } else {
            long longValue1 = date1.getTime();
            long longValue2 = date2.getTime();
            long difference = longValue1 - longValue2;
            long differenceSecond = Math.abs(difference) / (1000);
            return differenceSecond;
        }
    }

    /**
     * 字符串转化为日期
     *
     * @param str
     * @param format
     * @return
     */
    public static Date parseToDate(String str, String format) {
        DateFormat df = new SimpleDateFormat(format);
        Date date = null;
        try {
            date = df.parse(str);
        } catch (ParseException e) {

        }
        return date;
    }

    /**
     * 日期转化为字符串
     *
     * @param format
     * @return
     */
    public static String parseToString(Date date, String format) {
        DateFormat df = new SimpleDateFormat(format);
        String strDate = df.format(date);
        return strDate;
    }

    /**
     * 日期格式化DateFormat_yyyyMMddHHmmss字符串
     *
     * @param date
     * @return
     */
    public static String parseToString(Date date) {
        DateFormat df = new SimpleDateFormat(DateFormat_yyyyMMddHHmmss);
        String strDate = df.format(date);
        return strDate;
    }

    /**
     * 格式化日期
     */
    public static Date getFormatDate(Date date, String format) {
        if (date == null) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        String strDate = sdf.format(date);
        Date newDate = null;
        try {
            newDate = sdf.parse(strDate);
        } catch (ParseException e) {
            throw new RuntimeException("日期格式化出错");
        }
        return newDate;
    }

    /**
     * 获取某天开始（yyyy-MM-dd 00:00:00）
     *
     * @param date
     * @return
     */
    public static Date getBeginOfDay(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(DateFormat_yyyyMMdd);
        String temp = sdf.format(date);
        try {
            date = sdf.parse(temp);
        } catch (ParseException e) {
            throw new RuntimeException("日期格式化出错");
        }
        return date;
    }

    /**
     * 获取某天结束（yyyy-MM-dd 23:59:59）
     *
     * @param date
     * @return
     */
    public static Date getEndOfDay(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(DateFormat_yyyyMMdd);
        SimpleDateFormat sdf2 = new SimpleDateFormat(DateFormat_yyyyMMddHHmmss);
        String temp = sdf.format(date);
        Date newDate = null;
        try {
            newDate = sdf2.parse(temp + " 23:59:59");
        } catch (ParseException e) {
            throw new RuntimeException("日期格式化出错");
        }
        return newDate;
    }

    /**
     * 获取当前时间的时间戳
     *
     * @return
     */
    public static String getNowTimestamp() {
        Date date = new Date();
        return getDateTimestamp(date);
    }

    /**
     * 计算date减date1戳差(负数 为0)
     *
     * @return
     */
    public static long computeTimestamp(Date date, Date date1) {
        if (date == null || date1 == null) {
            return 0;
        }
        long thisTime = date.getTime();
        long anotherTime = date1.getTime();
        if (thisTime > anotherTime) {//如果当前时间小于指定的时间
            return thisTime - anotherTime;
        } else {
            return 0;
        }
    }

    /**
     * 获取指定时间的时间戳
     *
     * @param date
     * @return
     */
    public static String getDateTimestamp(Date date) {
        if (date != null) {
            String timestamp = parseToString(date, DateFormat_TimeStemp);
            return timestamp;
        }
        return null;
    }

    /**
     * 判断date1是否在date2前面
     *
     * @param date1
     * @param date2
     * @return 如果date1小于date2 return true,否则返回false
     */
    public static boolean isDate1BeforeDate2(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            throw new RuntimeException("时间比较不能为空");
        } else {
            return date1.before(date2);
        }
    }


    /**
     * 判断date1是否在date2后面
     *
     * @param date1
     * @param date2
     * @return 如果date1大于date2 return true,否则返回false
     */
    public static boolean isDate1AfterDate2(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            throw new RuntimeException("时间比较不能为空");
        } else {
            return date1.after(date2);
        }
    }

    /**
     * 判断date1和date2是否为同一个时间点
     *
     * @param date1
     * @param date2
     * @return
     */
    public static boolean isDate1EqualsDate2(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            throw new RuntimeException("时间比较不能为空");
        } else {
            return date1.equals(date2);
        }
    }

    /**
     * 设置当前时分秒到指定时间
     *
     * @param date
     * @return
     * @throws ParseException
     */
    public static Date setNowHHMMSSToThisDate(Date date) {
        Date nowDate = new Date();
        SimpleDateFormat formatHMS = new SimpleDateFormat(DateFormat_HHmmss);
        String nowDateHMS = formatHMS.format(nowDate);
        SimpleDateFormat formatYMD = new SimpleDateFormat(DateFormat_yyyyMMdd);
        String thisDateYMD = formatYMD.format(date);

        String resultDateStr = thisDateYMD + " " + nowDateHMS;
        SimpleDateFormat returnFormatYMD = new SimpleDateFormat(DateFormat_yyyyMMddHHmmss);
        Date parseDate = null;
        try {
            parseDate = returnFormatYMD.parse(resultDateStr);
        } catch (ParseException e) {
            throw new RuntimeException("日期格式化出错");
        }
        return parseDate;
    }

    /**
     * 获取该日期的所在月的第一天，零时零分零秒
     *
     * @param date
     * @return
     * @throws ParseException
     */
    public static Date getDateThisFirstDay(Date date) {
        date = getFormatDate(date, DateFormat_yyyyMMdd);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        return calendar.getTime();
    }

    /**
     * 获取该日期的所在月的最后一天，零时零分零秒
     *
     * @param date
     * @return
     * @throws ParseException
     */
    public static Date getDateThisLastDay(Date date) {
        date = getFormatDate(date, DateFormat_yyyyMMdd);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        return calendar.getTime();
    }

    /**
     * 获取时间范围内，每一天的零时零分零秒的日期列表（包括起止日期）
     *
     * @param startDate
     * @param endDate
     * @return
     * @throws ParseException
     */
    public static List<Date> getDateListByEveryDay(Date startDate, Date endDate) {
        startDate = getFormatDate(startDate, DateFormat_yyyyMMdd);
        endDate = getFormatDate(endDate, DateFormat_yyyyMMdd);
        List<Date> result = new ArrayList<Date>();
        for (Date date = startDate; date.compareTo(endDate) < 1; date = addDay(date, 1)) {
            result.add(date);
        }
        return result;
    }

    /**
     * 组装年月日（yyyy-MM-dd）
     *
     * @param year
     * @param month
     * @param day
     * @return
     * @throws ParseException
     */
    public static Date getDateByYearAndMonthAndDay(int year, int month, int day) {
        JDateTime jt = new JDateTime(year, month, day, 0, 0, 0, 0);
        return jt.convertToDate();
    }

    /**
     * 获取日期的月份
     *
     * @param date
     * @return
     */
    public static int getMonthOfDate(Date date) {
        JDateTime jt = new JDateTime(date);
        return jt.getMonth();
    }

    /**
     * 获取日期的日期
     *
     * @param date
     * @return
     */
    public static int getDayOfMonth(Date date) {
        JDateTime jt = new JDateTime(date);
        return jt.getDayOfMonth();
    }

}
